package com.atguigu.tingshu.comment.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.album.client.AlbumClientFeign;
import com.atguigu.tingshu.album.client.TrackClientFeign;
import com.atguigu.tingshu.comment.config.TextDetection;
import com.atguigu.tingshu.comment.service.CommentService;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.common.util.IdWorker;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.comment.Comment;
import com.atguigu.tingshu.user.client.UserClientFeign;
import com.atguigu.tingshu.vo.comment.CommentVo;
import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class CommentServiceImpl implements CommentService {

    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private RedisTemplate redisTemplate;
    @Resource
    private AlbumClientFeign albumClientFeign;
    @Resource
    private TrackClientFeign trackClientFeign;
    @Resource
    private UserClientFeign userClientFeign;
    @Autowired
    private TextDetection textDetection;
    @Autowired
    private IdWorker idWorker;

    /**
     * 保存新增评论
     *
     * @return
     */
    @Override
    @SneakyThrows
    public void saveComment(CommentVo commentVo) {
        // 校验参数
        if (commentVo == null ||
                commentVo.getAlbumId() == null ||
                commentVo.getTrackId() == null ||
                commentVo.getContent() == null) {
            throw new GuiguException(201, "参数错误");
        }
        // 校验登录状态
        Long userId = AuthContextHolder.getUserId();
        //
        Integer isVip = AuthContextHolder.getVip();
        if (userId == null) {
            throw new GuiguException(201, "评论需登录");
        }
        // 校验购买记录
        Long albumId = commentVo.getAlbumId();
        Long trackId = commentVo.getTrackId();
        // 专辑评分
        Integer albumCommentScore = commentVo.getAlbumCommentScore();
        // 评论内容
        String content = commentVo.getContent();
        // 评论所回复的评论id 一级评论默认 id = 0
        String replyCommentId = commentVo.getReplyCommentId();
        // 查询专辑付费类型：付费类型: 0101-免费、0102-vip免费、0103-付费
        AlbumInfo albumInfo = albumClientFeign.getAlbumInfo(albumId);
        String payType = albumInfo.getPayType();
        String priceType = albumInfo.getPriceType();
        // 专辑付费类型: 0102-vip免费
        if (payType.equals("0102")) {
            // 校验是否VIP
            if (isVip != 1) {
                throw new GuiguException(201, "非VIP");
            }
        } else if (payType.equals("0103")) {
            // 价格类型： 0201-单集 0202-整专辑
            if (priceType.equals("0201")) {
                // 单集购买场合 : key = trackId
                Map<String, Object> userPaidTrackMap = userClientFeign.getUserPaidTrack(trackId, userId);
                if (userPaidTrackMap.get(trackId) == null) {
                    throw new GuiguException(201, "声音未购买");
                }
            } else {
                // 整张购买的场合
                if (!userClientFeign.getUserPaidAlbum(albumId, userId)) {
                    throw new GuiguException(201, "专辑未购买");
                }
            }
        }
        // 校验当日评论限制 -- redis锁
        String redisKey = "CommentLock_" + userId + "_TrackId_" + trackId;
        Object commentFromRedis = redisTemplate.opsForValue().get(redisKey);
        if (commentFromRedis != null) {
            throw new GuiguException(201, "超出当天评论次数");
        }
        // 校验评论字数：10 < content < 100
        if (content.length() < 10) {
            throw new GuiguException(201, "评论不能小于10个字");
        } else if (content.length() > 100) {
            throw new GuiguException(201, "评论不能大于100字");
        }
        // 审核内容
        JSONObject jsonObject = textDetection.greenTextDetection(content);
        String suggestion = (String) jsonObject.get("Suggestion");
        // 返回值：Block：建议屏蔽，Review ：建议人工复审，Pass：建议通过
        if (!suggestion.equals("Pass")) {
            throw new GuiguException(201, "内容非法");
        }
        try {
            // 初始化
            Comment comment = new Comment();
            BeanUtils.copyProperties(commentVo, comment);
            // 属性补全
            comment.setId(idWorker.nextId() + "");
            comment.setUserId(userId);
            comment.setNickname(AuthContextHolder.getUsername());
            comment.setAvatarUrl("111");
            comment.setPraiseCount(0);
            comment.setCreateTime(new Date());
            comment.setIsPraise(false);
            comment.setReplyCommentList(null);
            comment.setParent(null);
            comment.setDeleteMark("1");
            // 同步写入MongoDB
            mongoTemplate.save(comment);
            // Redis上锁 --> 限定评论次数
            LocalDateTime now = LocalDateTime.now();
            // 获取当日最晚时间
            LocalDateTime endTime = LocalDateTime.of(now.toLocalDate(), LocalTime.MAX);
            Date expireTime = Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant());
            // 加锁限制评论频率
            redisTemplate.opsForValue().set(redisKey,
                    JSONObject.toJSONString(commentVo));
            redisTemplate.expireAt(redisKey, expireTime);
            // TODO-kfk发送异步通知 统计流水 更新专辑/声音统计表
        } catch (Exception e) {
            redisTemplate.delete(redisKey);
            throw e;
        }
    }


    /**
     * 分页查询评论
     *
     * @return
     */
    @Override
    public Object findCommentPage(Long albumId, Long trackId, Integer page, Integer size) {
        // 校验参数
        if (albumClientFeign.getAlbumInfo(albumId) == null) {
            throw new GuiguException(201, "专辑不存在");
        }
        if (!trackClientFeign.getTrackInfo(trackId)) {
            throw new GuiguException(201, "声音不存在");
        }
        // 条件构造
        Query query = new Query();
        query.addCriteria(Criteria
                .where("albumId").is(albumId)
                .and("trackId").is(trackId));
        query.with(Sort.by(Sort.Order.desc("createTime"))).limit(size);
        query.skip((page - 1) * size).limit(size);
        // 查mongodb后返回
        return mongoTemplate.find(query, Comment.class, "comment");
    }
}
